package com.is2.patchinglife.manager;

import java.lang.reflect.Type;
import java.util.Enumeration;
import java.util.Hashtable;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.is2.patchinglife.wrapper.AppConfiguration;
import com.is2.patchinglife.wrapper.GotTrophy;
import com.is2.patchinglife.wrapper.InfoTrophy;
import android.content.Context;

public class LocalDataManager{
	
	private static Context context;
	private static FileManager file_manager;
	
	private static AppConfiguration conf;
	private static Hashtable<String,GotTrophy> gotTrophy;	
	private static Hashtable<String,InfoTrophy> infoTrophy;

	private static int score = 0;
	private static int trNum = 0;												// number of trophies
	private static final String[] ranks = {"Noob","Grabber","Trophy Master"};
	private static int totPoints = 0;											// total possible score
	private static int totTrophies = 0;											// total number of trophies
	
	private LocalDataManager(){}
	
	
	/** :::::::::: PARSING METHODS :::::::::: **/
	
	/** Parse JSON local files into java class **/
	public static void parseLocalData(Context _context, String _user){
		context = _context;
		setFileManager(context);
		parseConf(_user);
		parseGotTrophy(_user);
		parseInfoTrophy();
	}
	
	
	/** Parse conf.json file into AppConfiguration.java **/
	public static AppConfiguration parseConf(String _username){
		
		// check guest user
		if(_username == null){
			_username="";
		}
		
		// parse file
		String s_conf = file_manager.read("conf"+_username+".json");
		conf = confFromJSON(s_conf);
		
		return conf;
	}

	
	/** Parse got_trophy.json file into GotTrophy.java **/
	public static Hashtable<String,GotTrophy> parseGotTrophy(String _username){
		
		// check guest user
		if(_username == null){ 
			_username="";
		}
		
		// parse file
		String s_got_trophy = file_manager.read("got_trophy"+_username+".json");
		gotTrophy = gotTrophyFromJSON(s_got_trophy);
		
		return gotTrophy;
	}
	
	
	/** Parse info_trophy.json file into InfoTrophy.java **/
	public static Hashtable<String,InfoTrophy> parseInfoTrophy(){
		
		// parse file
		String s_info_trophy = file_manager.read("info_trophy.json");
		infoTrophy = infoTrophyFromJSON(s_info_trophy);
		
		// set dynamically trophy IDs
		// [needed by NotificationHandler to not override multiple notifications]
		Enumeration<String> tk = infoTrophy.keys();
		int count = 0;
		while(tk.hasMoreElements()){
			String key = tk.nextElement();
			infoTrophy.get(key).setID(count++);
		}
		return infoTrophy;
	}
	
	
	
	/** :::::::::: FROM_JSON METHODS :::::::::: **/

	/** Parse string into AppConfiguration.java **/
	public static AppConfiguration confFromJSON(String _infoTrophy){
		Gson parser = new Gson();
		return parser.fromJson(_infoTrophy,AppConfiguration.class);
	}
	
	
	/** Parse string into GotTrophy.java **/
	public static Hashtable<String,GotTrophy> gotTrophyFromJSON(String _gotTrophy){
		Type type = new TypeToken<Hashtable<String,GotTrophy>>(){}.getType();		// define container type
		Gson parser = new Gson();
		return parser.fromJson(_gotTrophy,type);
	}

	
	/** Parse string into InfoTrophy.java **/
	public static Hashtable<String,InfoTrophy> infoTrophyFromJSON(String _infoTrophy){
		Type type = new TypeToken<Hashtable<String,InfoTrophy>>(){}.getType();
		Gson parser = new Gson();
		return parser.fromJson(_infoTrophy,type);
	}
	
	
	
	/** :::::::::: TO_JSON METHODS :::::::::: **/
	
	/** Parse AppConfiguration.java to JSON string **/
	public static String confToJSON(){
		Gson parser = new Gson();
		return parser.toJson(conf);
	}
	
	
	/** Parse GotTrophy.java to JSON string **/
	public static String gotTrophyToJSON(){
		Gson parser = new Gson();
		return parser.toJson(gotTrophy);
	}
	
	
	/** Parse InfoTrophy.java to JSON string **/
	public static String infoTrophyToJSON(){
		Gson parser = new Gson();
		return parser.toJson(infoTrophy);
	}
	
	
	
	/** :::::::::: SAVE FILE METHODS :::::::::: **/

	/** Saves conf file **/
	public static void saveConf(String _username) {
		
		// check guest user
		if(_username == null){
			_username="";
		}
		
		// parse to JSON
		String JSON = confToJSON();
		
		// save file
		file_manager.write(JSON, "conf"+_username+".json");
		
	}
	
	
	/** Saves gotTrophy file **/
	public static void saveGotTrophy(String _username) {
		
		// check guest user
		if(_username == null){
			_username="";
		}
		
		// parse to JSON
		String JSON = gotTrophyToJSON();
		
		// save file
		file_manager.write(JSON, "got_trophy"+_username+".json");
		
	}
	
	
	/** Saves infoTrophy file **/
	public static void saveInfoTrophy(){
		
		// parse to JSON
		String JSON = infoTrophyToJSON();
		
		// save file
		file_manager.write(JSON,"info_trophy.json");
		
	}
	
	
	
	/** :::::::::: TO_STRING METHODS :::::::::: **/
	
	
	/** Convert AppConfiguration to string **/
	public static String confToString(){
		return conf.toString();
	}

	
	/** Convert GotTrophy to string **/
	public static String gotTrophyToString(){
		String temp = "::::: GOT TROPHY LIST :::::\n";
		Enumeration<String> e = gotTrophy.keys();
		while(e.hasMoreElements()){
			String trophyList_key = (String) e.nextElement();
			temp += "KEY:"+trophyList_key+"\n";
			temp += gotTrophy.get(trophyList_key).toString()+"\n";
		}
		return temp;
	}

	
	/** Convert InfoTrophy to string **/
	public static String infoTrophyToString(){
		String temp = "::::: INFO TROPHY LIST :::::\n";
		Enumeration<String> e = infoTrophy.keys();
		while(e.hasMoreElements()){
			String trophyList_key = (String) e.nextElement();
			temp += "KEY:"+trophyList_key+"\n";
			temp += infoTrophy.get(trophyList_key).toString()+"\n";
		}
		return temp;
	}
	

		
	/** :::::::::: GET/SET METHODS :::::::::: **/
	public static Context getContext(){return context;}
	public static void setContext(Context _context){context = _context;}
	
	public static AppConfiguration getConf(){return conf;}
	public static void setConf(AppConfiguration _conf){conf = _conf;}
	
	public static Hashtable<String,GotTrophy> getGotTrophy(){return gotTrophy;}
	public static void setGotTrophy(Hashtable<String,GotTrophy> _got){gotTrophy = _got;}
	
	public static Hashtable<String,InfoTrophy> getInfoTrophy(){return infoTrophy;}
	public static void setInfoTrophy(Hashtable<String,InfoTrophy> _info){infoTrophy = _info;}
	
	public static FileManager getFileManager(){return file_manager;}
	public static void setFileManager(Context _context){file_manager = new FileManager(_context);}
	
	
	
	/** :::::::::: SET/GET SHORTCUTS :::::::::: **/
	
	/** CONF GET SHORTCUTS **/
	public static String getUser(){return conf.getUser();}
	public static boolean getInhibited(String _sens){
		try{
			return conf.getSensorConf().get(_sens).getInhibited();
		}catch(NullPointerException e){
			return true;
		}
	}
	public static boolean getEffects(){return conf.getEffects();}
	public static boolean getVibration(){return conf.getVibration();}
	
	
	/** GOT_TROPHY GET SHORTCUTS **/
	public static boolean getGotIT(String key){return gotTrophy.get(key).getGotIT();}
	public static String getDate(String key){return gotTrophy.get(key).getDate();}
	
	
	/**  INFO_TROPHY GET SHORTCUTS **/
	public static int getID(String key){return infoTrophy.get(key).getID();}
	public static String getName(String key){return infoTrophy.get(key).getName();}
	public static String getImage(String key){return infoTrophy.get(key).getImage();}
	public static String getDesc(String key){return infoTrophy.get(key).getDesc();}
	
	
	/** CONF SET SHORTCUTS **/
	public static void setUser(String _user){conf.setUser(_user);}
	public static void setInhibited(String _sens,boolean _inh){conf.getSensorConf().get(_sens).setInhibited(_inh);}
	public static void setEffects(boolean _e){conf.setEffects(_e);}
	public static void setVibration(boolean _v){conf.setVibration(_v);}
	
	
	
	/** :::::::::: UTILITY METHODS :::::::::: **/
	
	/** Update infos when a new trophy is obtained **/
	public static void gotNewTrophy(String key){
		gotTrophy.get(key).setGotIT(true);
		gotTrophy.get(key).setDate(null);
		String userToSave=null;
		if(LocalDataManager.getConf().isAuth()){
			userToSave = LocalDataManager.getUser();
		}
		saveGotTrophy(userToSave);
	}
	
	
	
	/** :::::::::: SCORE METHODS :::::::::: **/
	
	/** Update user score and number of trophies [and calculate total score]  **/
	public static void updateScore(){
		totPoints=0; trNum=0; score = 0; trNum = 0;
		
		Enumeration<String> e = gotTrophy.keys();
		while(e.hasMoreElements()){
			String k = (String)e.nextElement();
			
			// calculate user score
			if(gotTrophy.get(k).getGotIT()){
				score += infoTrophy.get(k).getPoints();
				trNum++;
			}
			
			// calculate tot score
			totPoints += infoTrophy.get(k).getPoints();
			totTrophies++;
		}
	}
	
	
	/** Calculate user rank **/
	public static String getRank(){
		int limit = totPoints/(ranks.length-1);		// calculate rank thresholds
		int index = (score+1)/limit;				// calculate rank
		return ranks[index];
	}
	
	
	/** Score get methods **/
	public static int getScore(){return score;}
	public static int getTrNum(){return trNum;}
	public static int getTotPoints(){return totPoints;}
	public static int getTotTrophies(){return totTrophies;}
}